<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" href="../rurple.css" type="text/css" />

<title>Fractions - part 2</title>
</head>
<body>
<h2 class="title">45. Fractions - part 2</h2>

<p>To multiply two fractions, like <tt>(1/2) * (3/4)</tt>, we need to
multiply the numerators together, do the same for the denominators, to get a
new fraction. For example:</p>

<pre>
1   3   3
- * - = -
2   4   8
</pre>

<p>Sometimes, when we multiply fractions, the result can be expressed in a
simpler form. For example:</p>

<pre>
2    11   22   1
-- * -- = -- = -
11   6    66   3
</pre>

<p>In this lesson, we will teach Python how to multiply two fractions, and
also how to simplify the result.</p>

<!--=============================================-->
<hr class="line" />

<h3 class="section">Multiplying two fractions</h3>

<p>With the two fractions defined in the last section, try to do the
following:</p>

<pre>
<span class='keyword'>    print</span> a*b
</pre>

<p><b>Try it!</b> You will get an error message, as Python does not know what it means to
have the symbol "<tt>*</tt>" between two objects of the class
<tt>Fraction</tt>. To tell Python to understand that the using the symbol
"<tt>*</tt>" between two fractions means that we want to multiply these two
fractions, we use the special function <tt>__mul__()</tt>. Here's our new
code:</p>

<pre>
<span class='linenumber'>  1 </span><span class=
'keyword'>class</span> Fraction(object):
<span class='linenumber'>  2 </span>    <span class=
'keyword'>def</span> __init__(self, numerator, denominator=<span class=
'number'>1</span>):
<span class='linenumber'>  3 </span>        self.num = numerator
<span class='linenumber'>  4 </span>        self.denom = denominator
<span class='linenumber'>  5 </span>        
<span class='linenumber'>  6 </span>    <span class=
'keyword'>def</span> __str__(self):
<span class='notelinenumber'>  7 </span>        <span class=
'keyword'>if</span> self.denom ==<span class='number'> 1</span>:
<span class='notelinenumber'>  8 </span>            <span class=
'keyword'>return</span><span class='string'> "(%s)"</span>%self.num
<span class='linenumber'>  9 </span>        <span class=
'keyword'>return</span><span class=
'string'> "(%s/%s)"</span>%(self.num, self.denom)
<span class='linenumber'> 10 </span>
<span class='newlinenumber'> 11 </span>    <span class=
'keyword'>def</span> __mul__(self, other):
<span class='newlinenumber'> 12 </span>        num = self.num * other.num
<span class=
'newlinenumber'> 13 </span>        denom = self.denom * other.denom
<span class='newlinenumber'> 14 </span><span class=
'keyword'>        return</span> Fraction(num, denom)
<span class='linenumber'> 15 </span>
<span class='linenumber'> 16 </span><span class=
'comment'>#== testing area below===
</span><span class='linenumber'> 17 </span>
<span class='linenumber'> 18 </span><span class=
'keyword'>if</span> __name__ ==<span class='string'> "__main__"</span>:
<span class='linenumber'> 19 </span>    a = Fraction(<span class=
'number'>1</span>,<span class='number'> 2</span>)
<span class='linenumber'> 20 </span>    b = Fraction(<span class=
'number'>3</span>,<span class='number'> 1</span>)
<span class='linenumber'> 21 </span><span class=
'keyword'>    assert</span> str(a) ==<span class='string'> "(1/2)"</span>
<span class='notelinenumber'> 22 </span><span class=
'keyword'>    assert</span> str(b) ==<span class='string'> "(3)"</span>
<span class='newlinenumber'> 23 </span><span class=
'keyword'>    print</span> a*b
</pre>

<p>First, I made some minor changes on lines 7, 8 and 22, so that the
denominator is not shown when it is equal to 1. This is slighly different
from the exercise I suggested in the last lesson, as I chose to keep the
parentheses to indicate it was still a object of the class <tt>Fraction</tt>
and not simply an integer.</p>

<p>Next, I told Python that, to multiply two fractions, you multiply the
numerators together [line 12], do the same with the denominators [line 13],
and that the result is a new <tt>Fraction</tt> object [line 14]. If you try
to run this program, the result [from line 23] will be "<tt>(3/2)</tt>",
which is what we want.</p>

<p>Now, let's turn the working print statement into an assert one [line 23],
and add a new test [lines 24 and 25], as indicated below.</p>

<pre>
<span class='linenumber'> 16 </span><span class=
'comment'>#== testing area below===
</span><span class='linenumber'> 17 </span>
<span class='linenumber'> 18 </span><span class=
'keyword'>if</span> __name__ ==<span class='string'> "__main__"</span>:
<span class='linenumber'> 19 </span>    a = Fraction(<span class=
'number'>1</span>,<span class='number'> 2</span>)
<span class='linenumber'> 20 </span>    b = Fraction(<span class=
'number'>3</span>,<span class='number'> 1</span>)
<span class='linenumber'> 21 </span><span class=
'keyword'>    assert</span> str(a) ==<span class='string'> "(1/2)"</span>
<span class='linenumber'> 22 </span><span class=
'keyword'>    assert</span> str(b) ==<span class='string'> "(3)"</span>
<span class='notelinenumber'> 23 </span><span class=
'keyword'>    assert</span> str(a*b) ==<span class='string'> "(3/2)"</span>
<span class='newlinenumber'> 24 </span>    c = Fraction(<span class=
'number'>1</span>,<span class='number'> 3</span>)
<span class='newlinenumber'> 25 </span><span class=
'keyword'>    print</span> b*c
</pre>

<p>If we run this program, we find that the output is "<tt>(3/3)</tt>" which
<i>we</i> recognize as being the same as <tt>1</tt>; it would be nice if
Python would do the same. To do that, we'll use an algorithm that was
invented more than 2000 years ago!</p>

<!--=============================================-->
<hr class="line" />

<h3 class="section">Euclid's algorithm</h3>

<p>In 300 BC (that is 300 years before year 0), the Greek philosopher Euclid
published a series of 13 books entitled <i>Elements</i>. Those books
contained what was known at the time about mathematics and geometry. Among
other things, an algorithm for finding the <i>greatest common divisor</i> (or
greatest common factor) was included It is very likely that this algorithm
had been known before Euclid was born; some people believe that it was first
discovered some 2500 years ago! Guido van Rossum, the creator of Python,
wrote a short function that implemented Euclid's algorithm:</p>

<pre>
<span class='keyword'>def</span> gcd(a, b):
    <span class='comment'>'''gcd returns the greatest common divisor 
       of given 2 integers.'''</span>
<span class='keyword'>    while</span> b:
        a, b = b, a%b
    <span class='keyword'>return</span> a
</pre>

<p>I will not explain Euclid's algorithm here. This is left as an exercise
for you. However, I will make use of it and define a new function to simplify
the results.</p>

<pre>
<span class='keyword'>def</span> simplify(a, b):
    <span class=
'comment'>'''divides two integers by their common factor.'''</span>
    common_factor = gcd(a, b)
    a /= common_factor
    b /= common_factor
<span class='keyword'>    return</span> a, b
</pre>

<p>Now, here's the new class definition:</p>

<pre>
<span class='newlinenumber'>  1 </span><span class=
'keyword'>def</span> gcd(a, b):
<span class='newlinenumber'>  2 </span>    <span class=
'comment'>'''gcd returns the greatest common divisor </span>
<span class='newlinenumber'>  3 </span><span class='comment'>        of given 2 integers.'''</span>
<span class='newlinenumber'>  4 </span><span class='keyword'>    while</span> b:
<span class='newlinenumber'>  5 </span>        a, b = b, a%b
<span class='newlinenumber'>  6 </span>    <span class='keyword'>return</span> a
<span class='linenumber'>  7 </span>
<span class='linenumber'>  8 </span><span class=
'keyword'>class</span> Fraction(object):
<span class='linenumber'>  9 </span>    <span class=
'keyword'>def</span> __init__(self, numerator, denominator=<span class=
'number'>1</span>):
<span class=
'notelinenumber'> 10 </span>        num, denom = self.simplify(numerator, denominator)
<span class='notelinenumber'> 11 </span>        self.num = num
<span class='notelinenumber'> 12 </span>        self.denom = denom
<span class='linenumber'> 13 </span>        
<span class='linenumber'> 14 </span>    <span class=
'keyword'>def</span> __str__(self):
<span class='linenumber'> 15 </span>        <span class=
'keyword'>if</span> self.denom ==<span class='number'> 1</span>:
<span class='linenumber'> 16 </span>            <span class=
'keyword'>return</span><span class='string'> "(%s)"</span>%self.num
<span class='linenumber'> 17 </span>        <span class=
'keyword'>return</span><span class=
'string'> "(%s/%s)"</span>%(self.num, self.denom)
<span class='linenumber'> 18 </span>
<span class='linenumber'> 19 </span>    <span class=
'keyword'>def</span> __mul__(self, other):
<span class='linenumber'> 20 </span>        num = self.num * other.num
<span class='linenumber'> 21 </span>        denom = self.denom * other.denom
<span class=
'newlinenumber'> 22 </span>        num, denom = self.simplify(num, denom)
<span class='linenumber'> 23 </span><span class=
'keyword'>        return</span> Fraction(num, denom)
<span class='linenumber'> 24 </span>
<span class='newlinenumber'> 25 </span>    <span class=
'keyword'>def</span> simplify(self, a, b):
<span class='newlinenumber'> 26 </span>        <span class=
'comment'>'''divides two integers by their common factor.'''</span>
<span class='newlinenumber'> 27 </span>        common_factor = gcd(a, b)
<span class='newlinenumber'> 28 </span>        a /= common_factor
<span class='newlinenumber'> 29 </span>        b /= common_factor
<span class='newlinenumber'> 30 </span><span class=
'keyword'>        return</span> a, b
<span class='linenumber'> 31 </span>
<span class='linenumber'> 32 </span><span class=
'comment'>#== testing area below===
</span><span class='linenumber'> 33 </span>
<span class='linenumber'> 34 </span><span class=
'keyword'>if</span> __name__ ==<span class='string'> "__main__"</span>:
<span class='linenumber'> 35 </span>    a = Fraction(<span class=
'number'>1</span>,<span class='number'> 2</span>)
<span class='linenumber'> 36 </span>    b = Fraction(<span class=
'number'>3</span>,<span class='number'> 1</span>)
<span class='linenumber'> 37 </span><span class=
'keyword'>    assert</span> str(a) ==<span class='string'> "(1/2)"</span>
<span class='linenumber'> 38 </span><span class=
'keyword'>    assert</span> str(b) ==<span class='string'> "(3)"</span>
<span class='newlinenumber'> 39 </span><span class=
'keyword'>    assert</span> str(a*b) ==<span class='string'> "(3/2)"</span>
<span class='newlinenumber'> 40 </span>    c = Fraction(<span class=
'number'>1</span>,<span class='number'> 3</span>)
<span class='newlinenumber'> 41 </span><span class=
'keyword'>    assert</span> str(b*c) ==<span class='string'> "(1)"</span>
<span class='notelinenumber'> 42 </span>    d = Fraction(<span class=
'number'>5</span>,<span class='number'> 10</span>)
<span class='notelinenumber'> 43 </span><span class=
'keyword'>    assert</span> str(d) ==<span class='string'> "(1/2)"</span>
</pre>

<p>In lines 1 to 6, we introduced our <tt>gcd()</tt> function.  By putting it outside the <span class="pykeyword">class</span> definition, we make it easily available to other programmers if they <span class="pykeyword">import</span> our file.  Just to show the other alternative, we put the method <tt>simplify()</tt> inside the <span class="pykeyword">class</span> definition, on lines 25 to 30.  We use <tt>simplify()</tt> on line 22 and test it on lines 39, 40 and 41.</p>

<p>We also use <tt>simplify()</tt> when we initialise a new fraction, on line 10 [with other minor changes on line 11 and 12] so that the newly created fraction will always be in simplified form.  This is tested on lines 42 and 43. </p>

<p>Look closely at the changes we made.  Everything works correctly, but there is one line that we added that wasn't required as it makes Python try to calculate the same thing twice.  <b>Can you see which one?</b> Try to find it, before moving on to the next lesson where we will divide fractions.</p>

<div class="lessons_nav">
<a href="44-fractions.htm"><img alt="previous" src=
"../../images/previous.png" />Fractions - Part 1</a> - 
<a href="../lessons_toc.htm"><img alt="home" src="../../images/home.png" />
</a> - <a href="46-fractions3.htm">Fractions - Part 3 <img alt="next"
src="../../images/next.png" /></a>
</div>
</body>
</html>
